/**
 * 定时器插件
 */
if (!Function.prototype.bind) {
    Function.prototype.bind = function (oThis) {
        if (typeof this !== "function") {
            throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
        }
        var aArgs = Array.prototype.slice.call(arguments, 1),
            fToBind = this,
            fNOP = function () {
            },
            fBound = function () {
                return fToBind.apply(this instanceof fNOP && oThis
                        ? this
                        : oThis,
                    aArgs.concat(Array.prototype.slice.call(arguments)));
            };
        fNOP.prototype = this.prototype;
        fBound.prototype = new fNOP();
        return fBound;
    };
}

(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD support
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // CommonJS support
        factory(require('jquery'));
    } else {
        // Browser globals support
        factory(jQuery);
    }
}(function ($) {
    // PRIVATE
    var options = {
            seconds: 0,									// 默认计时器开始秒数
            duration: null,								// 每隔{duration}执行一次回调
            callback: function () {
                console.log('time up');
            },
            startTimer: function () {
            },
            pauseTimer: function () {
            },
            resumeTimer: function () {
            },
            resetTimer: function () {
            },
            removeTimer: function () {
            },
            updateFrequency: 1000,//每隔1000毫秒执行一次
            state: 'running'
        },
        TIMER_STOPPED = 'stopped',
        TIMER_RUNNING = 'running',
        TIMER_PAUSED = 'paused';

    /**
     * 启动定时器
     * @param timer 将要启动定时器的对象
     */
    function startTimerInterval(timer) {
        var element = timer.element;
        $(element).data('intr', setInterval(incrementSeconds.bind(timer), timer.options.updateFrequency));
        $(element).data('isTimerRunning', true);
    }

    /**
     * 停止定时器
     * @param timer 将要停止定时器的对象
     */
    function stopTimerInterval(timer) {
        clearInterval($(timer.element).data('intr'));
        $(timer.element).data('isTimerRunning', false);
    }

    /**
     * 定时执行的函数
     */
    function incrementSeconds() {
        // 设备totalSeconds秒数
        $(this.element).data('totalSeconds', getUnixSeconds() - $(this.element).data('startTime'));
        // 每隔duration时间执行一次下面的代码
        if ($(this.element).data('duration') &&
            $(this.element).data('totalSeconds') % $(this.element).data('duration') === 0) {
            // 执行回调
            this.options.callback();
            $(this.element).trigger("nov.timer.run");
        }
    }

    /**
     * 获取系统当前的秒
     * @returns {number} 当前系统的时间秒
     */
    function getUnixSeconds() {
        return Math.round(new Date().getTime() / 1000);
    }

    /**
     * 时间转换成秒
     * @param time 时间
     * @returns {*} 秒
     */
    function timeToSeconds(time) {

        if (!isNaN(Number(time))) {
            return time;
        }

        var hMatch = time.match(/\d{1,2}h/),
            mMatch = time.match(/\d{1,2}m/),
            sMatch = time.match(/\d{1,2}s/),
            seconds = 0;

        if (hMatch) {
            seconds += Number(hMatch[0].replace('h', '')) * 3600;
        }
        if (mMatch) {
            seconds += Number(mMatch[0].replace('m', '')) * 60;
        }
        if (sMatch) {
            seconds += Number(sMatch[0].replace('s', ''));
        }
        return seconds;

    }

    /**
     * 开始定时
     * @param timer
     */
    function startTimer(timer) {
        var element = timer.element;
        if (!$(element).data('isTimerRunning')) {
            startTimerInterval(timer);
            $(element).data('state', TIMER_RUNNING);
            timer.options.startTimer.bind(timer).call();
            $(element).trigger("nov.timer.start");
        }
    }

    /**
     * 暂停定时
     * @param timer
     */
    function pauseTimer(timer) {
        var element = timer.element;
        if ($(element).data('isTimerRunning')) {
            stopTimerInterval(timer);
            $(element).data('state', TIMER_PAUSED);
            timer.options.pauseTimer.bind(timer).call();
            $(element).trigger("nov.timer.pause");
        }
    }

    /**
     * 恢复定时
     * @param timer
     */
    function resumeTimer(timer) {
        var element = timer.element;
        if (!$(element).data('isTimerRunning')) {
            $(element).data('startTime', getUnixSeconds() - $(element).data('totalSeconds'));
            startTimerInterval(timer);
            $(element).data('state', TIMER_RUNNING);
            timer.options.resumeTimer.bind(timer).call();
            $(element).trigger("nov.timer.resume");
        }
    }

    /**
     * 重启定时
     * @param timer
     */
    function resetTimer(timer) {
        var element = timer.element;
        $(element).data('startTime', 0);
        $(element).data('totalSeconds', 0);
        $(element).data('seconds', 0);
        $(element).data('state', TIMER_STOPPED);
        $(element).data('duration', timer.options.duration);
        timer.options.resetTimer.bind(timer).call();
        $(element).trigger("nov.timer.reset");
    }

    /**
     * 删除定时
     * @param timer
     */
    function removeTimer(timer) {
        var element = timer.element;
        stopTimerInterval(timer);
        timer.options.removeTimer.bind(timer).call();
        $(element).data('plugin_' + pluginName, null);
        $(element).data('seconds', null);
        $(element).data('state', null);
        $(element).trigger("nov.timer.remove");
    }

    /**
     * 时间对象
     * @param element 绑定定时器的对象
     * @param userOptions 参数对象
     * @constructor
     */
    var Timer = function (element, userOptions) {

        this.options = options = $.extend(this.options, options, userOptions);
        this.element = element;

        $(element).data('totalSeconds', options.seconds);

        $(element).data('startTime', getUnixSeconds() - $(element).data('totalSeconds'));

        $(element).data('seconds', $(element).data('totalSeconds'));
        $(element).data('state', TIMER_STOPPED);

        if (this.options.duration) {
            $(element).data('duration', timeToSeconds(this.options.duration));
            this.options.duration = timeToSeconds(this.options.duration);
        }

    };

    Timer.prototype = {
        start: function () {
            startTimer(this);
        },

        pause: function () {
            pauseTimer(this);
        },

        resume: function () {
            resumeTimer(this);
        },

        reset: function () {
            resetTimer(this);
        },

        remove: function () {
            removeTimer(this);
        }
    };

    var pluginName = 'timer';
    $.fn.nov = $.fn.nov || {};

    $.fn.nov[pluginName] = function (options) {
        options = options || 'start';

        var $this = $(this[pluginName]);
        return $this.each(function () {

            if (!($.data(this, 'plugin_' + pluginName) instanceof Timer)) {
                $.data(this, 'plugin_' + pluginName, new Timer(this, options));
            }

            var instance = $.data(this, 'plugin_' + pluginName);

            if (typeof options === 'string') {
                if (typeof instance[options] === 'function') {
                    instance[options].call(instance);
                }
            }

            if (typeof options === 'object') {
                instance.start.call(instance);
            }
        });

    };

}));
